package cc.rengu.igas.channel.cups.core.service.base;

import cc.rengu.igas.channel.cups.core.model.ChnlBizResponse;
import cc.rengu.igas.share.facade.bean.CupsField;
import cc.rengu.igas.share.facade.bean.CupsFieldBean;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.utility.util.BeanUtil;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * 支付业务处理基类
 *
 * @author who
 */
@SuppressWarnings({"AlibabaLowerCamelCaseVariableNaming", "AlibabaClassNamingShouldBeCamel", "rawtypes", "unchecked"})
public abstract class BasePayService<Q, P> extends BaseACService {

    private Class<P> PClass;
    private Class<Q> QClass;

    public BasePayService() {
        Type genType = getClass().getGenericSuperclass();
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        QClass = (Class) params[0];
        PClass = (Class) params[1];
    }

    @Override
    protected int bizInit(String s) {
        return 0;
    }

    @Override
    protected int bizProcess(String s, int i) {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        P resp = null;
        Q req = null;
        CupsFieldBean cupsFieldBean = new CupsFieldBean(new CupsField());
        try {
            //  请求  应答
            resp = PClass.newInstance();
            req = QClass.newInstance();
            ConvertUtil.convertOutput(req);

            /* Step1：通道(交易)权限检查 */
            rglog.info("---------------> 通道(交易)权限检查 <---------------");
            channelPermissionCheck();
            /* Step2：业务处理前实现接口 */
            rglog.info("---------------> 业务处理前处理 <---------------");
            req = beforeBizProcess(req);

            /* Step3：公共字段统一处理 */

            /* Step4：业务逻辑处理 */
            rglog.info("---------------> 业务逻辑处理 <---------------");
            BeanUtil.beanCopy(req, cupsFieldBean.getCupsField());
            ChnlBizResponse response = callBizService(cupsFieldBean, req, resp);
            /* Step4：业务处理后实现接口 */
            rglog.info("---------------> 业务处理后处理 <---------------");
            afterBizProcess(response);
            ConvertUtil.convertInput(resp);
        } catch (Exception e) {
            String respCode;
            String respMsg;
            rglog.error("业务异常信息:<{}>", cc.rengu.utility.base.StringUtil.ExceptionToString(e));
            if (e instanceof BizException) {
                respCode = ((BizException) e).getCode();
                respMsg = e.getMessage();
                rglog.error("业务处理失败，业务返回码:<{}>，业务返回信息:<{}>", respCode, respMsg);
            } else {
                rglog.error("系统处理失败，返回信息:<{}>", e);
                respCode = OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode();
                respMsg = OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc();
            }
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, respCode);
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, respMsg);
            } catch (Exception ex) {
                rglog.error("设置节点值异常信息:<{}>", cc.rengu.utility.base.StringUtil.ExceptionToString(e));
                return -1;
            }

        }
        return 0;
    }

    @Override
    protected int bizTerminate(String s) {
        return 0;
    }

    /**
     * 业务调用前处理
     *
     * @return 业务处理请求结构
     * @throws Exception 失败抛出异常
     */
    protected Q beforeBizProcess(Q request) throws Exception {
        return request;
    }

    /**
     * 业务处理服务调用
     *
     * @param request 业务处理信息
     * @return 业务处理应答结果
     * @throws Exception 失败抛出异常
     */
    protected abstract ChnlBizResponse callBizService(CupsFieldBean cupsFieldBean, Q request, P resp) throws Exception;

    /**
     * 业务调用后处理
     *
     * @param response 业务响应结果
     * @throws Exception 失败抛出异常
     */
    protected void afterBizProcess(ChnlBizResponse response) throws Exception {
    }
}
